// pub mod transform_component_reflection {

use std::{rc::Rc, cell::RefCell};

use lua::core::ToLuaValue;
use macro_def::reflection;
use crate::vulkan::object::object::{Componentable, Object, ComponentableContext};

use super::component::BaseComponent;
// use super::component::ObjectComponent;

#[reflection]
#[derive(Clone)]
pub struct TransfromComponent {
    base_component: BaseComponent,
    // special data
    translate: [f32; 3],
    rotation: [f32; 3],
    scale: [f32; 3]
}

impl Default for TransfromComponent {
    fn default() -> Self {
        Self {
            translate: [0.0, 0.0, 0.0],
            rotation: [0.0, 0.0, 0.0],
            scale: [1.0, 1.0, 1.0],

            base_component: BaseComponent::default()
        }
    }
}

impl ToLuaValue for TransfromComponent {
    fn to_lua_value(&mut self) -> lua::core::Value {
        lua::core::Value::Object((self as *mut Self as *mut std::ffi::c_void, "TransfromComponent"))
    }
}

impl TransfromComponent {
    fn get(instance: *const std::ffi::c_void, access_name: &String) -> lua::core::Value {
        unsafe {
            let self_instance = &mut *(instance as *mut Self);

            match access_name.as_str() {
                "scale" => lua::core::Value::Number(lua::core::LuaNumber::Float(self_instance.scale[0] as f64)),
                _ => lua::core::Value::Nil()
            }
        }   
    }

    fn set(instance: *const std::ffi::c_void, access_name: &String, value: &lua::core::Value) {
        unsafe {
            let self_instance = &mut *(instance as *mut Self);

            match access_name.as_str() {
                "scale" => {
                    if let lua::core::Value::Number(lua::core::LuaNumber::Float(value)) = value {
                        self_instance.set_scale(*value as f32);
                    }
                },
                _ => {
                    unreachable!()
                }
            }
        }   
    }
}

impl Componentable for TransfromComponent {
    fn post_load(&mut self, parent_object: Rc<RefCell<dyn Object>>, context: &mut ComponentableContext) {
        self.base_component.post_load(parent_object, context);
        
        context.lua_engine.getter_map_add(String::from("TransfromComponent"), Self::get);
        context.lua_engine.setter_map_add(String::from("TransfromComponent"), Self::set);
    }
}

// impl ObjectComponent for TransfromComponent {
//     fn post_load(&mut self, parent_object: std::rc::Rc<std::cell::RefCell<dyn crate::vulkan::object::object::Object>>) {
//         self.base_component.post_load(parent_object);
//     }
// }

impl TransfromComponent {
    pub fn to_matrix4(&self) -> cgmath::Matrix4<f32> {
        cgmath::Matrix4::from_translation(
            cgmath::Vector3{
                x: self.translate[0], 
                y: self.translate[1], 
                z: self.translate[2]}) * 
        cgmath::Matrix4::from_nonuniform_scale(
            self.scale[0],
            self.scale[1],
            self.scale[2]
        ) * 
        cgmath::Matrix4::from_angle_x(cgmath::Deg(self.rotation[0])) *
        cgmath::Matrix4::from_angle_y(cgmath::Deg(self.rotation[1])) *
        cgmath::Matrix4::from_angle_z(cgmath::Deg(self.rotation[2]))
    }

    pub fn add_translate(&mut self, x: f32, y: f32, z: f32) {
        self.translate = [self.translate[0] + x, self.translate[1] + y, self.translate[2] + z];
    }
    pub fn set_translate(&mut self, x: f32, y: f32, z: f32) {
        self.translate = [x, y, z];
    }

    pub fn set_rotation(&mut self, x: f32, y: f32, z: f32) {
        self.rotation = [x, y, z];
    }

    pub fn set_scale(&mut self, scale: f32) {
        self.scale = [scale, scale, scale];
    }
}